package com.apiauto.data_util;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.http.client.CookieStore;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.logging.log4j.util.Strings;

import com.alibaba.fastjson.JSONObject;
import com.apiauto.asserts.assertUtil;
import com.apiauto.dto.CaseDTO;
import com.apiauto.http_util.Request;
import com.apiauto.log.Log;
import com.apiauto.pojo.Case;
import com.apiauto.pojo.Rest;
import com.apiauto.pojo.Variable;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONArray;

/**
 * PS:用例工具类
 * @author lkk
 *
 */
public class CaseUtil {
	/**
	 * PS:根据获取字段,字段值获取指定表类型对象
	 * @param <T>
	 * @param field 指定字段名
	 * @param value 字段值
	 * @param list 检索的集合
	 * @param cellNames 相关表字段的集合
	 * @param clazz 集合实体类字节码对象
	 * @return 数据数组
	 */
	public static <T> Object[][] getExcelEntity(String field, String value, List<T> list,String[] cellNames,Class<T> clazz) {
		//存储遍历结果的集合
		List<T> resultList = new ArrayList<T>();
		//将字段名首字母大写
		StringBuffer sb = new StringBuffer(field);
		sb.replace(0, 1, String.valueOf(field.charAt(0)).toUpperCase());
		//get字段值方法名
		String methodString = "get" + sb.toString();
		//get方法对象
		Method method = null;
		try {
			method = clazz.getMethod(methodString);
		} catch (NoSuchMethodException | SecurityException e1) {
			Log.error("-----根据指定字段的值获取指定反射对象的方法对象失败-----");
		}
		//遍历接口信息对象集合,获取接口信息对象
		for (T excelEntity : list) {
			try {
				if (method.invoke(excelEntity).equals(value)) {
					T entity = excelEntity;
					resultList.add(entity);
				}
			} catch (Exception e) {
				Log.error("-----根据获取字段,字段值获取指定表类型对象方法在遍历获取反射对象时失败了-----");
			}
		}
		//调用方法转为二维对象数组
		Object[][] data = convertListforArrays(resultList, cellNames, clazz);
		return data;
	}
	
	/**
	 * PS:将指定泛型集合转为二维数组
	 * @param <T>
	 * @param list 需要转换的泛型集合
	 * @param cellNames 泛型相关实体类的字段数组
	 * @param clazz 泛型相关实体类的字节码对象
	 * @return 集合转换的二维数组
	 */
	public static <T> Object[][] convertListforArrays(List<T> list,String[] cellNames,Class<T> clazz) {
		//存放结果的二维数组
		Object[][] data = new Object[list.size()][cellNames.length];
		//遍历集合获取实体类对象
		for(int i=0;i<list.size();i++) {
			T entity = list.get(i);
			//遍历实体类.通过反射获取字段值
			for(int j=0;j<cellNames.length;j++) {
				try {
					//获取指定字段的get方法对象
					Method method = clazz.getMethod("get"+cellNames[j]);
					//调用get方法获取值
					String value = (String)method.invoke(entity);
					data[i][j] = value;
				} catch (Exception e) {
					Log.error("-----将指定泛型集合转为二维数组时调用反射方法失败-----");
				} 
			}
		}
		return data;
	}
	
	/**
	 * PS:将需要提取的变量放到集合中
	 * @param target 需要提取的字符串
	 * @param correlation 提取公式
	 */
	public static void extractVariable(String target, String correlation) {
		//将响应内容解析为JSONObject对象
		JSONObject jsonObject = JSONObject.parseObject(target);
		//拆除公式为数组
		String[] correlations = correlation.split("=");
		//变量名
		String key = correlations[0];
		//解析出公式提取层字符串数组
		String[] variables = correlations[1].split(",");
		//变量值
		String value = null;
		//遍历数组,根据公式层数解析出需要的变量值
		for(int i=0;i<variables.length;i++) {
			//截取出来的外围层数字段名
			String variable = variables[i].substring(variables[i].indexOf("[")+1,variables[i].indexOf("]"));
			//根据层数字段名获取字段值
			value = jsonObject.getString(variable);
			//判断字段值是否为空,不为空继续执行
			if(!Strings.isEmpty(value)) {
				//判断是否有注入cookie信息
				if(variable.equals("Set-Cookie")) {
					//JSESSIONID=6D650AA9D42EE3CC05E76B5E139CA8BB; Path=/; HttpOnly
					//取出JSESSIONID=6D650AA9D42EE3CC05E76B5E139CA8BB
					value = value.substring(value.indexOf(":")+1,value.indexOf(";"));
				}
				//数组字段值去除[]
				if(value.indexOf("[")!=-1&&value.indexOf("]")!=-1) {
					value = value.substring(value.indexOf("[")+1, value.indexOf("]"));
				}
				//只解析非最后一层(最后一层为结果)
				if(i<variables.length-1) {
					jsonObject = JSONObject.parseObject(value);
				}
			}
		}
		//将变量存入集合
		ExcelUtil.variableMap.put(key, value);
	}
	
	/**
	 *PS:将传入字符串的变量替换为值
	 * @param character 需要处理替换的字符串
	 */
	public static String replaceVariable(String character) {
		//遍历变量字典获取所有key值
		Set<String> variableSet = ExcelUtil.variableMap.keySet();
		//遍历key集合
		for(String key:variableSet) {
			//判断字符串中是否包含key值,存在则进行替换操作
			if(character.contains(key)) {
				String value = ExcelUtil.variableMap.get(key);
				character = character.replace(key, value);
			}
		}
		return character;
	}
	
	/**
	 * PS:检查点检查
	 * @param responseBody 响应主体信息
	 * @param checkPoint 检查点
	 * @return 断言是否通过
	 */
	public static boolean verifycheckPoint(String responseBody, String checkPoint){
		//去除空白符
		checkPoint = checkPoint.replaceAll("\\s*", "");
		//断言结果
		boolean flag = true;
		//获取{的索引
		int beginIndex = checkPoint.indexOf("{");
		//获取}的索引
		int endIndex = checkPoint.indexOf("}");
		//截取去掉{}的字符串
		checkPoint = checkPoint.substring(beginIndex+1, endIndex);
		if(checkPoint.indexOf(",")!=-1) {
			//按,分割获取字符串数组
			String[] checkPointArrays = checkPoint.split(",");
			//遍历字符串数组断言是否包含检查点数据
			for(String checkPointResult:checkPointArrays) {
				try {
					flag = assertUtil.check(responseBody, checkPointResult);
				} catch (AssertionError e) {
					flag = false;
					throw new AssertionError(e.getMessage());
				}
			}
		}else {
			flag = assertUtil.check(responseBody, checkPoint);
		}
		return flag;
	}
	
}
